package ASTInterpreter;

import java.util.Arrays;

import stone.Symbols;


// 可变长度数组环境
// 可以使用字典来存储(变量名, 变量)
// 其作用是, 用于存放全局变量, 而且可以随着解析的过程的推进, 逐步加入新的变量


public class ResizableArrayEnv extends ArrayEnv {

	protected Symbols names;  // 变量名与其所在的嵌套层(nest)和values数组中的下标的映射
	
	public ResizableArrayEnv() {
		super(10, null);
		
		names = new Symbols();
	}
	
	@Override
	public Symbols symbols() {
		return names;
	}
	
	public Object get(String name) {
		// 以变量名作为key, (递归)查询变量
		// 通过names获取变量下标, 然后以此下标去索引values数组
		// 如果找到, 返回该变量
		// 否则, 返回null
		Integer i = names.find(name);
		if (i == null) {
			if (outer == null) {
				return null;
			}
			else {
				return outer.get(name);
			}
		}
		else {
			return values[i];
		}
	}
	
	public void put(String name, Object value) {
		// 将(变量名, 变量)存入环境(env)
		// 首先(递归)查询存在这个变量名的环境env, 
		// 如果存在, 则将(变量名, 变量)存入环境env
		// 如果不存在, 以当前环境为存入环境存入(变量名, 变量)
		Environment env = where(name);
		if (env == null) {
			env = this;
		}
		env.putNew(name, value);
	}
	
	public void putNew(String name, Object value) {
		// 将(变量名, 变量值)存储下来
		// names.putNew返回name下标index
		// 将value按照index存入数组
		assign(names.putNew(name), value);
	}
	
	public Environment where(String name) {
		// 查找name对应的变量所在的环境(env)，并返回
		// 依次向外层查询，找到立即返回，不再继续查询
		if (names.find(name) != null) {
			return this;
		}
		else if (outer == null) {
			return null;
		}
		else {
			return outer.where(name);
		}
	}
	
	public void put(int nest, int index, Object value) {
		// 将value按照层次(nest)和下标(index)存入到values当中
		// 区分nest为0和大于0的情况
		if (nest == 0) {
			assign(index, value);
		}
		else {
			super.put(nest, index, value);
		}
	}
	
	protected void assign(int index, Object value) {
		// 将value存放到数组values的index位置
		// 超出数组values长度时，会进行数组扩展
		if (index >= values.length) {
			int newLen = values.length * 2;
			if (index >= newLen) {
				newLen = index + 1;
			}
			values = Arrays.copyOf(values, newLen);
		}
		values[index] = value;
	}

}
